package com.kingbook.core.sql;

import com.kingbook.core.cache.CacheConfig;
import com.kingbook.core.cache.SQLStatementParser;
import com.kingbook.core.scripting.SqlTemplate;
import com.kingbook.core.scripting.nodes.SqlNode;
import com.kingbook.core.sql.dialect.DBDialect;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;

/**
 * @Author: Bucky
 * @Date: 2019/1/2
 * @Version 1.0
 */
public class SqlFactory {

    private static Logger logger = LoggerFactory.getLogger(SqlFactory.class);

    private static Map<String, SqlTemplate> templateMap = Maps.newHashMap();

    public static void pushSqlTemplate(SqlTemplate sqlTemplate) {
        templateMap.put(sqlTemplate.getNamaspace(), sqlTemplate);
    }

    public static SqlContext getSqlContext(String sql, DBDialect dbDialect, CacheConfig cacheConfig) {
        List<String> tableNames = SQLStatementParser.parseTables(sql, dbDialect);
        if (cacheConfig != null && cacheConfig.isUseCache()) {
            if (cacheConfig.getCacheDuration() == 0)
                cacheConfig.setCacheDuration(tableNames.size() == 1 ? -1 : 300);
            logger.debug("[SQL]   Sql: {}", sql);
            return new SqlContext(sql, tableNames, cacheConfig);
        }
        return new SqlContext(sql,tableNames);
    }

    public static SqlContext getSqlContext(String sqlId, Map<String, ?> paramMap, DBDialect dbDialect) {
        int i = sqlId.indexOf(".");
        if (i <= 0)
            throw new IllegalArgumentException("[SqlFactory] sqlId 格式必须为： namespace.id");
        String namespace = sqlId.substring(0, i);
        SqlTemplate template = templateMap.get(namespace);
        Assert.notNull(template, "[SqlFactory] 找不到SQL namespace=" + namespace + " ");
        String id = sqlId.substring(i + 1);
        SqlNode sqlNode = template.getSqlNodeMap().get(id);
        Assert.notNull(sqlNode, "[SqlFactory] 找不到SQL sqlId=" + id);

        SqlContext sqlContext = sqlNode.getSqlContext(paramMap, template.getSegmentNodeMap(), dbDialect);
        logger.debug("[SQL] SqlId: {}.{}", namespace, id);
        logger.debug("[SQL]   Sql: {}", sqlContext.getSql());
        logger.debug("[SQL] Param: {}", paramMap == null ? "" : paramMap);
        return sqlContext;
    }

    public static SqlPageContext getSqlPageContext(String sqlId, Map<String, ?> paramMap, String countSqlId, Map<String, ?> countParamMap, int pageNo, int pageSize, DBDialect dbDialect) {
        SqlContext sqlContext = getSqlContext(sqlId, paramMap, dbDialect);
        SqlContext coutnSqlContext = getSqlContext(countSqlId, countParamMap, dbDialect);
        return new SqlPageContext(sqlContext, coutnSqlContext, pageNo, pageSize);
    }

    public static SqlPageContext getSqlPageContext(String sql, String countSql, int pageNo, int pageSize, DBDialect dbDialect, CacheConfig cacheConfig) {
        SqlContext sqlContext = getSqlContext(sql, dbDialect, cacheConfig);
        SqlContext coutnSqlContext = getSqlContext(countSql, dbDialect, cacheConfig);
        return new SqlPageContext(sqlContext, coutnSqlContext, pageNo, pageSize);
    }
}